package com.xing.binbackend.pattern.responsibility.ecommerce.product;

import com.xing.binbackend.pattern.responsibility.ecommerce.product.process.ProductInfoNotNullChainFilter;
import com.xing.binbackend.pattern.responsibility.ecommerce.product.process.ProductInventoryCheckChainFilter;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeansException;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// 定义每个处理器的通用行为
@Component
public final class MerchantAdminChainContext<T> implements ApplicationContextAware, CommandLineRunner {
    /**
     * 应用上下文，通过Spring IOC获取Bean实例
     */
    private ApplicationContext applicationContext;

    /**
     * 保存商品上架责任链实现类
     * <p>
     * Key：{@link MerchantAdminAbstractChainHandler#mark()}
     * Val：{@link MerchantAdminAbstractChainHandler} 一组责任链实现 Spring Bean 集合
     * <p>
     * 比如有一个商品上架模板创建责任链，实例如下：
     * Key：MERCHANT_ADMIN_CREATE_PRODUCT_TEMPLATE_KEY
     * Val：
     * - 验证商品信息基本参数是否必填 —— 执行器  {@link ProductInfoNotNullChainFilter}
     * - 验证商品库存 —— 执行器 {@link ProductInventoryCheckChainFilter}
     */
    private final Map<String, List<MerchantAdminAbstractChainHandler>> abstractChainHandlerContainer = new HashMap<>();

    /**
     * 责任链组件执行
     * @param mark 责任链组件标识
     * @param requestObj 请求参数
     */
    public void handler(String mark,ProductUpShelfReqDTO requestObj){
        // 根据 mark 标识从责任链容器中获取一组责任链实现 Bean 集合
        List<MerchantAdminAbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.get(mark);
        if (CollectionUtils.isEmpty(abstractChainHandlers)) {
            throw new RuntimeException(String.format("[%s] Chain of Responsibility ID is undefined.", mark));
        }
        abstractChainHandlers.forEach(each -> each.handler(requestObj));
    }

    /**
     * 执行方法，接收可变参数
     * 本方法主要用于初始化和处理商品上架抽象责任链容器
     * 它从Spring容器中获取所有MerchantAdminAbstractChainHandler类型的Bean，
     * 并根据它们的mark进行分类和排序，以便后续处理
     *
     * @param args 可变参数，可能包含方法运行所需的额外信息
     * @throws Exception 如果方法执行过程中遇到错误，抛出异常
     */
    @Override
    public void run(String... args) throws Exception {
        Map<String, MerchantAdminAbstractChainHandler> chainFilterMap = applicationContext.getBeansOfType(MerchantAdminAbstractChainHandler.class);
        // 遍历所有获取到的Bean，并将它们根据mark分类存入抽象责任链容器中
        chainFilterMap.forEach((beanName, bean) -> {
            // 判断 Mark 是否已经存在抽象责任链容器中，如果已经存在直接向集合新增；如果不存在，创建 Mark 和对应的集合
            List<MerchantAdminAbstractChainHandler> abstractChainHandlers = abstractChainHandlerContainer.getOrDefault(bean.mark(), new ArrayList<>());
            abstractChainHandlers.add(bean);
            abstractChainHandlerContainer.put(bean.mark(), abstractChainHandlers);
        });
        // 遍历抽象责任链容器，对每个 Mark 对应的责任链实现类集合进行排序
        abstractChainHandlerContainer.forEach((mark, chainHandlers) -> {
            // 对每个 Mark 对应的责任链实现类集合进行排序，优先级小的在前
//            chainHandlers.sort(Comparator.comparing(Ordered::getOrder));
        });
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}